#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2021/7/30 15:11
# @Author  : Samge
import json
import time
from multiprocessing import Manager

from PyQt5.QtCore import QThread

from itkz.controls.proxy_agent_splash import CommonCbStatus
from itkz.resources.utils import config_util
from itkz.spider_ext import settings


class BaseControl(object):
    """
    control基类
    """

    process = None
    log_thread = None
    gui = None

    def name(self):
        return self.gui.name()

    def __init__(self, gui):
        self.gui = gui

    def init_cb_list(self, cb_obj, lst, save_key=None):
        """
        初始化下拉选择框的数据
        :param cb_obj: 下拉框对象
        :param lst: 下拉框的数据库列表
        :param save_key: 保存的配置名
        :return:
        """
        lst = lst if lst is not None else []
        if save_key:
            lst = lst + list(config_util.value(f"{self.name()}/{save_key}", []))
        cb_obj.addItems(lst)

    def save_cb_list(self, cb_obj, lst, save_key=None, add_value=None):
        """
        处理下拉选择框的数据更新 与 保存
        :param cb_obj: 下拉框对象
        :param lst: 下拉框的数据库列表
        :param save_key: 保存的配置名
        :param add_value: 要添加的值
        :return:
        """
        curr_value = add_value or cb_obj.currentText() or ''
        # if not curr_value:
        #     return
        lst = lst if lst is not None else []
        is_change = curr_value not in lst or lst.index(curr_value) != 0
        if curr_value in lst:
            lst.remove(curr_value)
        lst.insert(0, curr_value)
        if is_change:
            cb_obj.clear()
            cb_obj.addItems(lst)
        if save_key:
            config_util.setValue(f"{self.name()}/{save_key}", lst or [])

    def to_json_str(self, obj):
        return json.dumps(obj, ensure_ascii=False).replace('\n', '')

    def release(self):
        """ 释放资源 """
        self.terminate(self.process)
        self.terminate(self.log_thread)
        self.gui = None

    def onSpiderClose(self):
        """
        爬虫结束触发
        :return:
        """
        pass


class BaseLogQueueControl(BaseControl):

    """
    有日志打印队列的control基类
    """

    process = None
    cb_status = None

    def __init__(self, gui):
        super().__init__(gui)
        self.cb_status = CommonCbStatus(gui)
        # 初始化日志队列与日志读取线程
        self.log_queue = Manager().Queue()
        self.log_thread = LogThread(self)

    def get_log_widget(self):
        return None

    def clearLog(self):
        """
        清空日志内容
        :return:
        """
        tv_log = self.get_log_widget()
        if not tv_log:
            raise ValueError("请先初始化 get_log_widget() 方法")
        tv_log.clear()

    def printLog(self, v):
        """
        在ui上打印（显示）日志信息
        :param v:
        :return:
        """
        tv_log = self.get_log_widget()
        if not tv_log:
            raise ValueError("请先初始化 get_log_widget() 方法")
        v = str(v)
        v = f"{v}\n" if len(v) > 50 and not str(v).endswith('\n') else v
        print(v)
        tv_log.append(v)

    def reset_status(self):
        """
        清空消息队列 与 日志打印面板，重置按钮文本
        :return:
        """
        start_time = time.time()
        while not self.log_queue.empty():
            self.log_queue.get()
        self.clearLog()
        self.onSpiderClose()
        self.terminate(self.process)
        self.terminate(self.log_thread)
        self.log_queue.put(f"reset_status完成，共耗时：{time.time() - start_time} 秒")

    def release(self):
        """ 释放资源 """
        super().release()
        self.terminate(self.process)
        self.terminate(self.log_thread)
        self.gui = None

    def terminate(self, obj):
        try:
            if obj:
                obj.terminate()
                self.printLog(f"terminate 成功")
        except Exception as e:
            self.printLog(f"terminate 失败：{e}")

    def onSpiderClose(self):
        try:
            if self.process:
                self.process.stop()
                self.printLog(f"self.process.stop() 成功")
        except Exception as e:
            self.printLog(f"self.process.stop() 失败 e：{e}")
        pass


class LogThread(QThread):
    """
    从队列中取出数据显示
    """
    def __init__(self, control):
        super(LogThread, self).__init__()
        self.control = control

    def run(self):
        while True:
            if self.control.log_queue.empty():
                continue
            log_txt = self.control.log_queue.get()
            self.control.printLog(log_txt)
            if settings.CLOSE_SPIDER_TIP in log_txt:
                self.control.onSpiderClose()
                break
            # 睡眠，否则太快会导致QTextBrowser闪退或者显示乱码
            self.msleep(20)
